#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: create_ticket.py

##
# Módulos del sistema
# Parte gráfica
try:
    import pygtk
    pygtk.require("2.0")
    import gtk
    import gtk.glade
except ImportError, error:
    print error
    print "Necesitas la librería gráficas gtk+pygtk"

##
# Utilidades
import os
from datetime import datetime

##
# Módulos propios
try:
    from lib.database import Empleado, Clasificacion, GrupoDeResolucion
except ImportError, error:
    print error
    print "Problemas con la BD en: '/gui/create_ticket.py'"
try:
    from lib.config import WIDTH, HEIGHT
    from gui.msj_retroalimentacion import MensajeDeAdvertencia, MensajeDeError
    from lib.funciones_utiles import close, add_find_column
except ImportError, error:
    print error
    print "No se pudo cargar el archivo (create_ticket.py)"

class CreateTicket:
    """Crear ticket.

    Clase que permitira el manejo de la interfaz de creación de ticket.
    Utilizado en el CDU-01 Registrar Ticket

    """
    def __init__(self, padre, usuario_logueado):
        self.gladefile = "gui/ghhp.glade"
        self.wTree = gtk.glade.XML(self.gladefile,"create_ticket")
        self.window = self.wTree.get_widget("create_ticket")
        self.window.resize(WIDTH,250)
        self.hbox_62 = self.wTree.get_widget("hbox62")
        self.hbox_64 = self.wTree.get_widget("hbox64")
        self.hbox_65 = self.wTree.get_widget("hbox65")
        self.hbox_156 = self.wTree.get_widget("hbox156")
        self.entry_legajo_empleado = self.wTree.get_widget("entry70")
        self.entry_apellido_empleado = self.wTree.get_widget("entry71")
        self.entry_nombre_empleado = self.wTree.get_widget("entry72")
        self.entry_codigo_clasificacion = self.wTree.get_widget("entry73")
        self.entry_nombre_clasificacion = self.wTree.get_widget("entry74")
        self.entry_descripcion = self.wTree.get_widget("textview6")
        self.wTree.get_widget("label_numero_ticket").set_text('FIXME')
        self.un_dict={"on_button37_clicked": self.validate_create_ticket,
                "on_button38_clicked": self.close,
                "on_button41_clicked": self.derivar_ticket,
                "on_button40_clicked": self.close_ticket,
                "on_button111_clicked": self.close,
                "on_button110_clicked": self.validate_derivar_ticket}
        self.wTree.signal_autoconnect(self.un_dict)

        ##
        # Requerimiento especial del CDU. Con <Enter> pasamos de entry
        self.conect_entry_enter()
        # Agregamos fecha y hora actual
        self.fecha_creacion = datetime.now()
        self.fecha, self.hora = self.fecha_creacion.strftime("%Y:%m:%d %H:%M:%S").split()
        self.wTree.get_widget("label_fecha_apertura").set_text(self.fecha)
        self.wTree.get_widget("label_hora_apertura").set_text(self.hora)
        # Variables necesarias para registrar ticket   
        self.padre = padre
        self.empleado_solicitante = None 
        self.usuario_logueado = usuario_logueado
    
    def contenedor(self):
        return self.wTree.get_widget("vbox43")

    def conect_entry_enter(self):
        """Permite generar the activate signal para los widget"""
        def grab_focus(widget, other):
            other.grab_focus()
            self.completar_campos()

        def groups(lista, n, step=1):
            for index in xrange(0, len(lista)-(n-1), step):
                yield lista[index:index+n]

        path =(self.entry_legajo_empleado,
                self.entry_apellido_empleado,
                self.entry_nombre_empleado,
                self.entry_codigo_clasificacion,
                self.entry_nombre_clasificacion,
                self.entry_descripcion)

        for from0, to in groups(path, 2):
            from0.connect("activate", grab_focus, to)

    def completar_campos(self):
        """Completará los campos de entrada.

        Busca en la base de datos el nombre y apellido del Empleado con legago
        "nro_legajo" y la Clasificación con "nro_clasificacion", y los muestro
        en los campos correspondientes luedo de presionar <Enter> desde la
        funcion conect_entry_enter.

        Keyword arguments:
        None
        """
        nro_legajo = self.entry_legajo_empleado.get_text()
        nro_clasificacion = self.entry_codigo_clasificacion.get_text()

        if nro_legajo != '':
            # Levantar el apellido y nombre con este legajo
            consulta = Empleado.selectBy(legajo = nro_legajo)
            try:
                empleado = consulta[0]
                self.entry_apellido_empleado.set_text(empleado.apellido)
                self.entry_nombre_empleado.set_text(empleado.nombre)
                self.empleado_solicitante = empleado
                self.entry_codigo_clasificacion.grab_focus()
            except IndexError, error:
                print error
                msj = "Nro. de legajo inexistente en el Sistema de Personal."
                print msj
                msj_error = MensajeDeError(msj, self.window)
                msj_error.run()
                self.entry_legajo_empleado.set_text('')
                self.entry_legajo_empleado.grab_focus()
        if nro_clasificacion !='':
            # Levantar el nombre de este codigo de clasificacion
            consulta = Clasificacion.selectBy(id = nro_clasificacion)
            try:
                clasificacion = consulta[0]
                self.entry_nombre_clasificacion.set_text(clasificacion.nombre)
                self.clasificacion_problema = clasificacion
                self.entry_descripcion.grab_focus()
            except IndexError, error:
                print error
                msj = "Codigo de clasificacion inexistente en el Sistema."
                print msj
                msj_error = MensajeDeError(msj, self.window)
                msj_error.run()
                self.entry_codigo_clasificacion.set_text('')
        if (nro_legajo == '' and
                self.entry_apellido_empleado.get_text() !='' and
                self.entry_nombre_empleado.get_text()):
            consulta = Empleado.selectBy(
                    apellido = self.entry_apellido_empleado.get_text(),
                    nombre = self.entry_nombre_empleado.get_text())
            try:
                empleado = consulta[0]
                entry_legajo_empleado.set_text(empleado.legajo)
                self.empleado_solicitante = empleado
                print self.empleado_solicitante
            except IndexError, error:
                print error
                msj = "Empleado inexistente en el Sistema de Personal."
                msj_error = MensajeDeError(msj, self.window)
                msj_error.run()
                self.entry_legajo_empleado.set_text('')
                self.entry_apellido_empleado.set_text('')
                self.entry_nombre_empleado.set_text('')
                self.entry_legajo_empleado.grab_focus()

    def run(self):
        #self.w_create_ticket = self.wTree.get_widget("create_ticket")
        #gtk.main()
        pass

    def datos_no_validos(self):
        """Valida los datos de entrada para CREAR TICKET.

        Comprueba todos lo campos obligatorios necesarios para completar esta
        actividad, ellos son:
        -Legajo
        -Clasificacion
        -Descripcion del problema-

        Keyword arguments:
        None
        """
        if (self.entry_legajo_empleado.get_text() == "" or
               self.entry_codigo_clasificacion.get_text() == "" or
               self.texto_descripcion == "" ):
            #Caso 1
            error = "- Legajo\n- Clasificacion\n- Observaciones\n No pueden ser nulos"
            return True, error
        else:
            #Caso2:
            return False, ""

    def validate_create_ticket(self, widget):
        """Llama a datos_no_validos.

        Dependiendo de lo que retorna datos_no_validos mostrará la informacion
        necesaria para la proxima actividad -cerrar ó derivar-

        Keyword arguments:
        widget -- Widget de crear ticket

        """
        descripcion = self.wTree.get_widget("textview6").get_buffer()
        start = descripcion.get_start_iter()
        end = descripcion.get_end_iter()
        self.texto_descripcion = descripcion.get_text(start,end)
        #!!!FIXME: el texto viene UTF-8. Tenemos que pasarlo a Unicode

        datos_no_validos,error = self.datos_no_validos()
        if datos_no_validos:
            msj_error = MensajeDeError(error, self.window)
            msj_error.run()
        else:
            # Sistema registra el ticket como "abierto en mesa de ayuda"
            # !!! FIXME :al tener simultaneidad no se si deberia ser un pop(),
            # sino que deberiamos buscarlo por el numero. Lo solucione haciendo
            # que el mismo constructor me devuelva la posicion en la cual fue
            # agregado, asi solo resta con buscar.
            self.ticket = self.padre.mesa_de_ayuda.crearTicket(
                            self.padre.usuario_logueado,
                            self.empleado_solicitante,
                            self.clasificacion_problema,
                            self.texto_descripcion,
                            self.fecha_creacion)
            self.hbox_62.hide()
            # Se deben mostrar en el hbox64 los datos que pide la
            # especificacion del caso de uso nro_1
            self.wTree.get_widget("legajo_cliente").set_text(
                    self.empleado_solicitante.legajo)
            self.wTree.get_widget("apellido_cliente").set_text(
                    self.empleado_solicitante.apellido)
            self.wTree.get_widget("nombre_cliente").set_text(
                    self.empleado_solicitante.nombre)
            self.wTree.get_widget("codigo_clasificacion").set_text(
                    str(self.clasificacion_problema.id))
            self.wTree.get_widget("nombre_clasificacion").set_text(
                    self.clasificacion_problema.nombre)
            self.wTree.get_widget("numero_ticket").set_text(
                    str(self.padre.mesa_de_ayuda.tickets[self.ticket.id].id))
            self.wTree.get_widget("textview20").get_buffer().set_text(
                    self.texto_descripcion)
            self.wTree.get_widget("label271").set_text(self.fecha)
            self.wTree.get_widget("label272").set_text(self.hora)
            self.hbox_65.show()
            self.wTree.get_widget("textview9").grab_focus()
            self.hbox_64.show()
            self.window.resize(WIDTH,HEIGHT)

    def derivar_ticket(self, widget):
        """Deriva el ticket al grupo de resolucion que selecciona el usuario.

        Tenemos que validar observacion y ademas hacer hbox49 show() que ahí se
        encuentra la informacion de los grupos de resolucion. Datos necesarios
        para la derivacion de ticket.

        """
        self.wTree.get_widget("vbox49").show()
        self.hbox_156.hide()
        self.obs, bandera = self.observacion_valida()
        if bandera:
            self.armar_lista_de_grupos()

    def validate_derivar_ticket(self, widget):
        """
        """
        grupo, seleccionado = self.un_grupo_seleccionado()
        if seleccionado:
            texto = "¿Está seguro que desea derivar el reclamo?"
            msj = MensajeDeAdvertencia(texto, self.window)
            if msj.msj.run() == gtk.RESPONSE_YES:
                print self.lista_grupos[grupo]
                # Derivamos ticket
                fecha_derivacion = datetime.now()

                self.padre.mesa_de_ayuda.derivarTicket(self.lista_grupos[grupo],
                        fecha_derivacion,
                        self.obs,
                        self.padre.usuario_logueado,
                        self.ticket)
                self.window.destroy()
            else:
                msj.msj.destroy()
        else:
            texto = "Debe seleccionar el Grupo al cual se derivará el ticket."
            msj = MensajeDeError(texto, self.window)
            msj.run()

    def un_grupo_seleccionado(self):
        """Permite comprobar si selecciono un grupo de la lista.


        """
        model, path = self.list_view_grupos.get_selection().get_selected_rows()
        if path:
            pos, = path[0]
            return pos, True
        else:
            return "", False

    def armar_lista_de_grupos(self):
        """Permite completra el treeview31 con los grupos habilidatos."""
        self.lista_grupos = []
        resultado = GrupoDeResolucion.select()
        for grupo in resultado:
            if self.clasificacion_problema in grupo.clasificaciones:
                self.lista_grupos.append(grupo)
        # Armamos las cabeceras de la lista de grupos
        self.list_view_grupos = self.wTree.get_widget("treeview31")
        titulos = ["Numero", "Nombre"]
        for pos, titulo in enumerate(titulos):
            add_find_column(titulo, pos, self.list_view_grupos)
        self.find_list = gtk.ListStore(str, str)
        self.list_view_grupos.set_model(self.find_list)
        # Completamos con los grupos
        for grupo in self.lista_grupos:
            self.find_list.append([str(grupo.id), grupo.nombre])

    def add_find_column(self, title, columnId):
        """Agrega una columna al la lista de grupos habilitados.

        Keyword arguments:
        title -- Título de la columna
        columnId -- posicion donde queremos la columna
        """
        column = gtk.TreeViewColumn(title, gtk.CellRendererText(),
                text=columnId)
        column.set_resizable(True)
        column.set_sort_column_id(columnId)
        self.list_view_grupos.append_column(column)

    def observacion_valida(self):
        """Valida el campo Observaciones.

        Este campo es un dato obligatorio, tanto para la derivacion como para
        el cierre de un reclamo.

        Keyword arguments:
        None
        """
        obs = self.wTree.get_widget("textview9").get_buffer()
        start = obs.get_start_iter()
        end = obs.get_end_iter()
        if obs.get_text(start, end) != "":
            return obs.get_text(start, end), True
        else:
            msj = "Observacion no puede ser nulo en esta operacion."
            print msj
            msj_error = MensajeDeError(msj, self.window)
            msj_error.run()
            return "", False

    def close_ticket(self, widget):
        """CDU03 Cerrar ticket.

        Cerrará el ticket almacenando la fecha y hora actual.
        """
        obs, bandera = self.observacion_valida()
        if bandera:
            texto = "¿Está seguro que desea cerrar el reclamo?"
            msj = MensajeDeAdvertencia(texto, self.window)
            if msj.msj.run() == gtk.RESPONSE_YES:
                print "Cerrando reclamo..."
                fecha_cierre = datetime.now()
                self.padre.mesa_de_ayuda.cerrarTicket(self.padre.usuario_logueado,
                        obs,
                        fecha_cierre,
                        self.ticket)
                self.window.destroy()
            else:
                msj.msj.destroy()

    def close(self, widget):
        close(self.window)
